package controller

import (
	"github.com/cn-ygf/go-admin/internal/action"
	"github.com/cn-ygf/go-admin/internal/modular/system/model"
	"github.com/cn-ygf/go-admin/internal/modular/system/service"
	"github.com/cn-ygf/go-admin/internal/modular/system/vo"
	"github.com/cn-ygf/go-admin/pkg/utils"
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/mvc"
	"github.com/xuri/excelize/v2"
	"net/http"
	"strconv"
)

// UsersController 用户管理
type UsersController struct {
	Ctx iris.Context
}

// PostList 分页查询用户
func (c *UsersController) PostList(req vo.QueryUserListReq) mvc.Result {
	if !hasPermi(c.Ctx, "system:user:list") {
		return nil
	}
	var (
		err   error
		list  []*model.SysUser
		total int64
	)

	if req.PageSize > 1000 {
		req.PageSize = 1000
	}
	if req.Params != nil {
		req.Params.BeginTime = req.Params.BeginTime / 1000
		req.Params.EndTime = req.Params.EndTime / 1000
	}
	deptMaps, err := service.DeptService.GetMaps()
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	list, total, err = service.UserService.QueryList(&req)
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	resultList := make([]*vo.QueryUserListEntity, len(list))
	for index, item := range list {
		resultList[index] = &vo.QueryUserListEntity{
			UserID:      item.UserID,
			DeptID:      item.DeptID,
			DeptName:    deptMaps[item.DeptID],
			UserName:    item.UserName,
			NickName:    item.NickName,
			UserType:    item.UserType,
			Email:       item.Email,
			Phonenumber: item.Phonenumber,
			Sex:         item.Sex,
			Avatar:      item.Avatar,
			Status:      item.Status,
			Remark:      item.Remark,
			CreatedAt:   item.CreatedAt,
		}
	}
	return action.Data(map[string]any{
		"rows":  resultList,
		"total": total,
	})
}

// GetDeptTree 用户管理查询树形部门
func (c *UsersController) GetDeptTree() mvc.Result {
	if !hasPermi(c.Ctx, "system:user:list") {
		return nil
	}
	root, err := service.DeptService.SelectTree()
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	return action.Data(root)
}

// PutStatus 修改用户状态
func (c *UsersController) PutStatus(req vo.ChangeUserStatusReq) mvc.Result {
	if !hasPermi(c.Ctx, "system:user:edit") {
		return nil
	}
	var (
		err error
	)
	if req.Status != "0" && req.Status != "1" {
		return action.ParamError()
	}
	err = service.UserService.ChangeStatus(req.UserId, req.Status)
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	return action.OK()
}

// PutPwd 修改用户密码
func (c *UsersController) PutPwd(req vo.ResetUserPwdReq) mvc.Result {
	if !hasPermi(c.Ctx, "system:user:resetPwd") {
		return nil
	}
	var (
		err error
	)
	if service.UserService.IsAdmin(req.UserId) {
		return action.AdminError()
	}
	err = service.UserService.ChangePassword(req.UserId, req.Password)
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	return action.OK()
}

// GetBy 根据id查询单个用户
func (c *UsersController) GetBy(id int64) mvc.Result {
	if !hasPermi(c.Ctx, "system:user:query") {
		return nil
	}
	user, err := service.UserService.GetByID(id)
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	roleIds, err := service.UserService.GetUserRoleIdsByID(user.UserID)
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	postIds, err := service.UserService.GetUserPostIdsByID(user.UserID)
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	return action.Data(map[string]any{
		"user": map[string]any{
			"userId":      user.UserID,
			"userName":    user.UserName,
			"nickName":    user.NickName,
			"phonenumber": user.Phonenumber,
			"email":       user.Email,
			"sex":         user.Sex,
			"status":      user.Status,
			"deptId":      user.DeptID,
			"remark":      user.Remark,
		},
		"postIds": postIds,
		"roleIds": roleIds,
	})
}

// GetOptions 获取role/post选项
func (c *UsersController) GetOptions() mvc.Result {
	if !hasPermi(c.Ctx, "system:user:query") {
		return nil
	}
	roleList, err := service.RoleService.GetList()
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	roles := make([]map[string]any, len(roleList))
	for index, item := range roleList {
		roles[index] = map[string]any{
			"roleId":    item.RoleID,
			"roleName":  item.RoleName,
			"roleKey":   item.RoleKey,
			"createdAt": item.CreatedAt,
		}
	}
	postList, err := service.PostService.GetList()
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	posts := make([]map[string]any, len(postList))
	for index, item := range postList {
		posts[index] = map[string]any{
			"postId":   item.PostID,
			"postName": item.PostName,
		}
	}
	return action.Data(map[string]any{
		"posts": posts,
		"roles": roles,
	})
}

// DeleteBy 删除用户
func (c *UsersController) DeleteBy(idStr string) mvc.Result {
	if !hasPermi(c.Ctx, "system:user:remove") {
		return nil
	}
	ids := utils.IdsStrToInt64(idStr)
	if len(ids) < 1 {
		return action.ParamError()
	}
	if utils.IdsContains(ids, 1) {
		return action.AdminError()
	}
	err := service.UserService.Delete(ids)
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	return action.OK()
}

// Post 添加用户
func (c *UsersController) Post(req vo.AddUserReq) mvc.Result {
	if !hasPermi(c.Ctx, "system:user:add") {
		return nil
	}
	var (
		err error
	)
	req.CreateBy = getCurrentUser(c.Ctx).UserName
	err = service.UserService.Add(&req)
	if err != nil {
		return action.ServerError()
	}
	return action.OK()
}

// Put 修改用户资料
func (c *UsersController) Put(req vo.EditUserReq) mvc.Result {
	if !hasPermi(c.Ctx, "system:user:edit") {
		return nil
	}
	var (
		err error
	)
	if service.UserService.IsAdmin(req.UserId) {
		return action.AdminError()
	}
	req.UpdateBy = getCurrentUser(c.Ctx).UserName
	err = service.UserService.Update(&req)
	if err != nil {
		return action.Error(err.Error())
	}
	return action.OK()
}

// PostImport 导入用户
func (c *UsersController) PostImport() mvc.Result {
	if !hasPermi(c.Ctx, "system:user:import") {
		return nil
	}
	updateSupport := false
	updateSupportStr := c.Ctx.URLParam("updateSupport")
	if updateSupportStr == "true" {
		updateSupport = true
	}
	currentUser := getCurrentUser(c.Ctx)
	_, fh, err := c.Ctx.FormFile("file")
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	f, err := fh.Open()
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	defer f.Close()
	ef, err := excelize.OpenReader(f)
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	defer ef.Close()
	rows, err := ef.Rows("Sheet1")
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	sexMaps, err := service.DictDataService.GetDictMapsEx("sys_user_sex")
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	statusMaps, err := service.DictDataService.GetDictMapsEx("sys_normal_disable")
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.ServerError()
	}
	isFirst := true
	defaultPassword := "123456"
	defaultPasswordCfg := service.ConfigService.Get("sys.user.initPassword")
	if defaultPasswordCfg != nil {
		defaultPassword = defaultPasswordCfg.ConfigValue
	}
	addUserList := make([]*vo.AddUserReq, 0)
	for rows.Next() {
		row, err := rows.Columns()
		if err != nil {
			break
		}
		if isFirst {
			isFirst = false
			continue
		}
		if len(row) != 7 {
			continue
		}
		deptId, _ := strconv.ParseInt(row[0], 10, 64)
		addUserList = append(addUserList, &vo.AddUserReq{
			UserName:    row[1],
			NickName:    row[2],
			Email:       row[3],
			Phonenumber: row[4],
			Sex:         sexMaps[row[5]],
			Status:      statusMaps[row[6]],
			Remark:      "",
			Password:    utils.EncryptPassword(defaultPassword),
			DeptId:      deptId,
			PostIds:     nil,
			RoleIds:     nil,
			CreateBy:    currentUser.UserName,
		})
	}
	return action.Data(service.UserService.Import(addUserList, updateSupport))
}

// GetTemplate 用户导入模板下载
func (c *UsersController) GetTemplate() int {
	c.Ctx.ResponseWriter().Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
	row := []string{"部门编号", "登录名称", "姓名", "邮箱", "手机号码", "性别", "状态"}
	f := excelize.NewFile()
	defer f.Close()
	cell, err := excelize.CoordinatesToCellName(1, 1)
	if err != nil {
		systemLog.Errorln(err.Error())
		return http.StatusInternalServerError
	}
	f.SetSheetRow("Sheet1", cell, &row)
	err = f.Write(c.Ctx.ResponseWriter())
	if err != nil {
		systemLog.Errorln(err.Error())
	}
	return http.StatusOK
}

// PostExport 导出用户
func (c *UsersController) PostExport() mvc.Result {
	if !hasPermi(c.Ctx, "system:user:export") {
		return action.RawError()
	}
	userList, err := service.UserService.All()
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.RawError()
	}
	titleRow := []string{"用户序号", "登录名称", "姓名", "邮箱", "手机号码", "性别", "状态", "最后登录IP", "最后登录时间", "部门", "部门负责人"}
	sexMaps, err := service.DictDataService.GetDictMaps("sys_user_sex")
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.RawError()
	}
	statusMaps, err := service.DictDataService.GetDictMaps("sys_normal_disable")
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.RawError()
	}
	deptMaps, err := service.DeptService.GetMapsEx()
	if err != nil {
		systemLog.Errorln(err.Error())
		return action.RawError()
	}
	data := make([][]any, len(userList))
	for index, item := range userList {
		row := make([]any, 11)
		row[0] = item.UserID
		row[1] = item.UserName
		row[2] = item.NickName
		row[3] = item.Email
		row[4] = item.Phonenumber
		row[5] = sexMaps[item.Sex]
		row[6] = statusMaps[item.Status]
		row[7] = item.LoginIP
		row[8] = utils.UnixTimeToString(item.LoginDate)
		row[9] = ""
		row[10] = ""
		dept, ok := deptMaps[item.DeptID]
		if ok {
			row[9] = dept.DeptName
			row[10] = dept.Leader
		}
		data[index] = row

	}
	return action.ExportExcel(data, titleRow)
}

// PutRole 分配角色
func (c *UsersController) PutRole(req vo.PutUserRoleReq) mvc.Result {
	if !hasPermi(c.Ctx, "system:user:edit") {
		return nil
	}
	err := service.UserService.AuthRole(req.UserId, req.RoleIds)
	if err != nil {
		return action.ServerError()
	}
	return action.OK()
}
